// ------------------------------------------------------------------------------------------------
// File   : DX9VertexShaderManager.cpp
// Date   : 2012-08-01
// Author : Weng xiao yi
// Descr. : Manage vertex shaders
//          Handles creation by building the shader definition based on requested features
//
// ------------------------------------------------------------------------------------------------


// ------------------------------------------------------------------------------------------------
// HEADERS
// ------------------------------------------------------------------------------------------------
#include "DX9ShaderUtils.h"
#include "DX9VertexShader.h"
#include "DX9VertexShaderManager.h"
#include "DX9ShaderDatabase.h"
#include "Shaders\DX9FeatureDefinitions.h"
// ------------------------------------------------------------------------------------------------
// CONSTANTS
// ------------------------------------------------------------------------------------------------

const CHAR DX9VS_SHADER_ENTRY[]  = "VSMain";


// vertex header format Input : ---------------------------------------------------------
// %s - platform specific defines
// %s - features defines
// %s - common include file
// %s - shader name
// --------------------------------------------------------------------------------------
const CHAR DX9VS_SHADER_FORMAT[] = 
"\n%s\n\n"                                                            \
"%s\n\n"                                                              \
"#include \"DX9FeatureDefinitions.h\"\n"                              \
"#include \"VsCommon.hlsl\"\n"                                        \
"#include \"%s.hlsl\"\n"                                              \
"VSOUT VSMain( VSIN Input )\n"                                        \
"{\n"                                                                 \
"    return ProcessVertex( Input );\n"                                \
"}\n\n"                                                               \
;

// Available input components
const CHAR DX9VS_COMPONENT_COLOR0[]    = "INPUT_COLOR0";
const CHAR DX9VS_COMPONENT_COLOR1[]    = "INPUT_COLOR1";
const CHAR DX9VS_COMPONENT_BLENDINFO[] = "INPUT_BLENDINFO";
const CHAR DX9VS_COMPONENT_NORMAL[]    = "INPUT_NORMAL";
const CHAR DX9VS_COMPONENT_TANGENT[]   = "INPUT_TANGENT";
const CHAR DX9VS_COMPONENT_TEXCOORD0[] = "INPUT_TEXCOORD0";
const CHAR DX9VS_COMPONENT_TEXCOORD1[] = "INPUT_TEXCOORD1";
const CHAR DX9VS_COMPONENT_TEXCOORD2[] = "INPUT_TEXCOORD2";
const CHAR DX9VS_COMPONENT_TEXCOORD3[] = "INPUT_TEXCOORD3";
const CHAR DX9VS_COMPONENT_TEXCOORD4[] = "INPUT_TEXCOORD4";
const CHAR DX9VS_COMPONENT_TEXCOORD5[] = "INPUT_TEXCOORD5";
const CHAR DX9VS_COMPONENT_TEXCOORD6[] = "INPUT_TEXCOORD6";
const CHAR DX9VS_COMPONENT_TEXCOORD7[] = "INPUT_TEXCOORD7";



const char* FDX9VSMaterialsDesc[] =
{
	"VSDefault",
	"VSAfterEffect",
	"VsAdvancedWater",
	"VsSpaceBump",
	"VsSoftParticle",
	"VsDynamicWeather"
};

// ------------------------------------------------------------------------------------------------
// IMPLEMENTATION
// ------------------------------------------------------------------------------------------------



DX9VertexShaderManager::DX9VertexShaderManager()
{ 
}

DX9VertexShaderManager::~DX9VertexShaderManager()
{
	UnloadAll();
}

void DX9VertexShaderManager::Shutdown(void)
{
	UnloadAll();
}

void DX9VertexShaderManager::UnloadAll(void)
{
	UnloadAllShaders();
}

void DX9VertexShaderManager::UnloadAllShaders(void)
{
	MapVertexShader::iterator it = m_mapLoadedShaders.begin();
	while(it != m_mapLoadedShaders.end())
	{
		delete it->second;
		it->second = NULL;
		it++;
	}
	m_mapLoadedShaders.clear();
}

void DX9VertexShaderManager::BuildShaderDefinition(DX9VSFeature* _poFeatures, char *_szShaderDefinition)
{
	if(_poFeatures->UseAssemble())
		sprintf_s(_szShaderDefinition, 4096, "%s", _poFeatures->GetAssembleShader());
	else
		sprintf_s(_szShaderDefinition, 4096, DX9VS_SHADER_FORMAT, 
			"",	_poFeatures->BuildFeatureDefinition(m_szFeatures),     // feature defines
			FDX9VSMaterialsDesc[_poFeatures->GetMaterialID()]          // shader name
	);
}

// ------------------------------------------------------------------------------------------------
// Name   : GetShader
// Params : Feature list to support
// RetVal : The appropriate compiled shader
// Descr. : Try to find an already compiled shader having the required features. 
//          Else request a shader compilation
// ------------------------------------------------------------------------------------------------
DX9VertexShader* DX9VertexShaderManager::GetShader(DX9VSFeature* _poFeatures)
{
	// look for cached vertex shader for current key
	MapVertexShader::iterator it = m_mapLoadedShaders.find( _poFeatures->GetKey() );

	if( it != m_mapLoadedShaders.end( ) )
	{
		// use cached vertex shader
		return it->second;
	}
	else
	{
		if(GenerateShader(_poFeatures))
		{
			it = m_mapLoadedShaders.find(_poFeatures->GetKey());
			DX9Verify( it != m_mapLoadedShaders.end() );
			return it->second;
		}
		else
		{
			// could not generate shader			
			OutputDebugStringA("Unable to create vertex shader ");
		}
	}

	return NULL;
}

// ------------------------------------------------------------------------------------------------
// Name   : GenerateShader
// Params : Required shader feature set
// RetVal : Shader successfully created or not
// Descr. : Build shader definition then push a request for a shader.
//          A fake default entry will automatically be created then the shader compilation thread
//          will asynchronously compile the required shader and swap when done.
// ------------------------------------------------------------------------------------------------
BOOL DX9VertexShaderManager::GenerateShader(DX9VSFeature* _poFeatures)
{
	DX9ShaderMacro  oMacros;
	ULONG           ulFlags         = 0;
	char            szShaderDefinition[4096];

	// Macro settings
	oMacros.Clear();

	// using the defined features and material type, generate a shader definition
	BuildShaderDefinition(_poFeatures, szShaderDefinition);

	// Request compilation of that shader
	DX9GetShaderDatabase()->RequestVertexShader(_poFeatures->GetKey(), szShaderDefinition, DX9VS_SHADER_ENTRY, ulFlags, oMacros);

	return TRUE;
}

// ------------------------------------------------------------------------------------------------
// Name   : CreateShader
// Params : Shader key, code, constant table and name
// RetVal : A useable vertex shader
// Descr. : Create a useable vertex shader entity
// ------------------------------------------------------------------------------------------------
DX9VertexShader* DX9VertexShaderManager::CreateShader(const ULONG64& _ulKey, const void* _pCode, ID3DXConstantTable* _pConstantTable, CHAR* _szName)
{
	DX9Verify(_pCode != NULL);

	DX9VertexShader* pShader = NULL;

	pShader = new DX9VertexShader();
	if(pShader == NULL)
		return NULL;

	if(_pConstantTable)
	{
		pShader->SetConstantTable(_pConstantTable);
	}

	if(pShader->ReInit( (DWORD *)_pCode, (SHADERVERSION(_ulKey) < 20) ) == FALSE)
	{
		delete pShader;
		pShader = NULL;
		return NULL;
	}

#ifdef SHADER_DEBUG
	pShader->SetFilename(_szName);
#endif

	return pShader;
}

// ------------------------------------------------------------------------------------------------
// Name   : AddShader
// Params : The shader and its key 
// RetVal : 
// Descr. : Try to find an already present shader using this key. Replace old one if found,
//          create a new entry in the vertex shader map if not.
// ------------------------------------------------------------------------------------------------
void DX9VertexShaderManager::AddShader(const ULONG64& _ulKey, DX9VertexShader* _pShader)
{
	MapVertexShader::iterator it = m_mapLoadedShaders.find(_ulKey);

	if(it != m_mapLoadedShaders.end())
	{
		delete it->second;
		it->second = NULL;
		it->second = _pShader;
	}
	else
	{
		m_mapLoadedShaders[_ulKey] = _pShader;
	}
}

// ------------------------------------------------------------------------------------------------
// Name   : AddCreateShader
// Params : 
// RetVal : 
// Descr. : Create and add a new vertex shader
// ------------------------------------------------------------------------------------------------
void DX9VertexShaderManager::AddCreateShader(const ULONG64& _ulKey, const void* _pCode, ID3DXConstantTable* _pConstantTable)
{
	DX9VertexShader*	pVertexShader;
	char                szShaderName[64];

	sprintf_s(szShaderName, "0x%016I64x.hlsl", _ulKey);

	pVertexShader = CreateShader(_ulKey, _pCode, _pConstantTable, szShaderName);

	AddShader(_ulKey, pVertexShader);
}

// ------------------------------------------------------------------------------------------------
// Name   : PreLoadShader
// Params : 
// RetVal : 
// Descr. : Add an entry for a previously compiled shader (shaderdatabase). The constant table 
//          will automatically be generated by the create shader.
// ------------------------------------------------------------------------------------------------
void DX9VertexShaderManager::PreLoadShader(const ULONG64& _ulKey, void* _pCode)
{
	AddCreateShader(_ulKey, _pCode, NULL);
}

// ------------------------------------------------------------------------------------------------
// Name   : BuildFeatureDefinition
// Params : 
// RetVal : 
// Descr. : Feature string builder entry point for all vertex shaders
// ------------------------------------------------------------------------------------------------
const char* DX9VertexShaderManager::DX9VSFeature::BuildFeatureDefinition(char* _szFeatureDefinition)
{
	_szFeatureDefinition[0] = '\0';

	// Define the input components
	DX9_APPEND_DEFINE(HasColor0(),    DX9VS_COMPONENT_COLOR0);
	DX9_APPEND_DEFINE(HasColor1(),    DX9VS_COMPONENT_COLOR1);
	DX9_APPEND_DEFINE(HasBlendInfo(), DX9VS_COMPONENT_BLENDINFO);
	DX9_APPEND_DEFINE(HasNormal(),    DX9VS_COMPONENT_NORMAL);
	DX9_APPEND_DEFINE(HasTangent(),   DX9VS_COMPONENT_TANGENT);
	DX9_APPEND_DEFINE(HasTexCoord0(), DX9VS_COMPONENT_TEXCOORD0);
	DX9_APPEND_DEFINE(HasTexCoord1(), DX9VS_COMPONENT_TEXCOORD1);
	DX9_APPEND_DEFINE(HasTexCoord2(), DX9VS_COMPONENT_TEXCOORD2);
	DX9_APPEND_DEFINE(HasTexCoord3(), DX9VS_COMPONENT_TEXCOORD3);
	DX9_APPEND_DEFINE(HasTexCoord4(), DX9VS_COMPONENT_TEXCOORD4);
	DX9_APPEND_DEFINE(HasTexCoord5(), DX9VS_COMPONENT_TEXCOORD5);
	DX9_APPEND_DEFINE(HasTexCoord6(), DX9VS_COMPONENT_TEXCOORD6);
	DX9_APPEND_DEFINE(HasTexCoord7(), DX9VS_COMPONENT_TEXCOORD7);

	// Let the child class add it's custom definitions
	AddSpecificFeatures(_szFeatureDefinition);

	return _szFeatureDefinition;
}

// ------------------------------------------------------------------------------------------------
// Name   : DX9VertexShaderManager::DX9VSFeatureAfterEffect::AddSpecificFeatures
// Descr. : Add specific after effect features
// ------------------------------------------------------------------------------------------------
void DX9VertexShaderManager::DX9VSFeatureAfterEffect::AddSpecificFeatures(CHAR* _szFeatureDefinition)
{
	char szTemp[512];

	// After Effect Id
	sprintf_s(szTemp, "AFTER_EFFECT_ID %d", stKey.ulEffectId);
	DX9_APPEND_DEFINE(1, szTemp);

	// After Effect sub type
	sprintf_s(szTemp, "AFTER_EFFECT_SUB_TYPE %d", stKey.ulEffectSubType);
	DX9_APPEND_DEFINE(1, szTemp);

	// Samples count
	sprintf_s(szTemp, "AFTER_EFFECT_SAMPLE_COUNT %d", stKey.ulSamplesCount);
	DX9_APPEND_DEFINE(1, szTemp);

	DX9_APPEND_DEFINE(stKey.ulInputTexCoord0, "INPUT_TEXCOORD0");
}

void DX9VertexShaderManager::DX9VSFeatureAfterEffect::PreCache()
{
	DX9VertexShader* pVertexShader = NULL;

	DX9VertexShaderManager::DX9VSFeatureAfterEffect oVSFeature1;
	oVSFeature1.stKey.ulShaderVer	  = 20;
	oVSFeature1.stKey.ulEffectId      = AE_TYPE_BLOOM_DOWNSAMPLE;
	oVSFeature1.stKey.ulEffectSubType = 0;
	pVertexShader = DX9GetVertexShaderManager()->GetShader(&oVSFeature1);

	DX9VertexShaderManager::DX9VSFeatureAfterEffect oVSFeature2;
	oVSFeature2.stKey.ulShaderVer	  = 20;
	oVSFeature2.stKey.ulEffectId      = AE_TYPE_BLOOM_BLUR;
	oVSFeature2.stKey.ulEffectSubType = 0;
	pVertexShader = DX9GetVertexShaderManager()->GetShader(&oVSFeature2);

	DX9VertexShaderManager::DX9VSFeatureAfterEffect oVSFeature3;
	oVSFeature3.stKey.ulShaderVer	  = 20;
	oVSFeature3.stKey.ulEffectId      = AE_TYPE_BLOOM_COMBINE;
	oVSFeature3.stKey.ulEffectSubType = 0;
	pVertexShader = DX9GetVertexShaderManager()->GetShader(&oVSFeature3);

	DX9VertexShaderManager::DX9VSFeatureAfterEffect oVSFeature4;
	oVSFeature4.stKey.ulShaderVer	  = 20;
	oVSFeature4.stKey.ulEffectId      = AE_TYPE_FOG_LINEAR;
	oVSFeature4.stKey.ulEffectSubType = 0;
	pVertexShader = DX9GetVertexShaderManager()->GetShader(&oVSFeature4);

	DX9VertexShaderManager::DX9VSFeatureAfterEffect oVSFeature4_1;
	oVSFeature4_1.stKey.ulShaderVer		= 20;
	oVSFeature4_1.stKey.ulEffectId      = AE_TYPE_FOG_LINEAR;
	oVSFeature4_1.stKey.ulEffectSubType = AE_TYPE_FOG_LINEAR_EXP;
	pVertexShader = DX9GetVertexShaderManager()->GetShader(&oVSFeature4_1);

	DX9VertexShaderManager::DX9VSFeatureAfterEffect oVSFeature4_2;
	oVSFeature4_2.stKey.ulShaderVer		= 20;
	oVSFeature4_2.stKey.ulEffectId      = AE_TYPE_FOG_LINEAR;
	oVSFeature4_2.stKey.ulEffectSubType = AE_TYPE_FOG_LINEAR_EXP2;
	pVertexShader = DX9GetVertexShaderManager()->GetShader(&oVSFeature4_2);

	DX9VertexShaderManager::DX9VSFeatureAfterEffect oVSFeature6;
	oVSFeature6.stKey.ulShaderVer	  = 20;
	oVSFeature6.stKey.ulEffectId      = AE_TYPE_FOG_LAYERED;
	oVSFeature6.stKey.ulEffectSubType = 0;
	pVertexShader = DX9GetVertexShaderManager()->GetShader(&oVSFeature6);

	DX9VertexShaderManager::DX9VSFeatureAfterEffect oVSFeature7;
	oVSFeature7.stKey.ulShaderVer	  = 20;
	oVSFeature7.stKey.ulEffectId      = AE_TYPE_FXAA;
	oVSFeature7.stKey.ulEffectSubType = 0;
	pVertexShader = DX9GetVertexShaderManager()->GetShader(&oVSFeature7);

	DX9VertexShaderManager::DX9VSFeatureAfterEffect oVSFeature8_1;
	oVSFeature8_1.stKey.ulShaderVer		= 20;
	oVSFeature8_1.stKey.ulEffectId      = AE_TYPE_DOF;
	oVSFeature8_1.stKey.ulEffectSubType = AE_TYPE_DOF_TWO_KERNEL_HEXAGONS;
	pVertexShader = DX9GetVertexShaderManager()->GetShader(&oVSFeature8_1);


	DX9VertexShaderManager::DX9VSFeatureAfterEffect oVSFeature8_3;
	oVSFeature8_3.stKey.ulShaderVer		= 20;
	oVSFeature8_3.stKey.ulEffectId      = AE_TYPE_DOF;
	oVSFeature8_3.stKey.ulEffectSubType = AE_TYPE_DOF_COMBINE;
	pVertexShader = DX9GetVertexShaderManager()->GetShader(&oVSFeature8_3);

	DX9VertexShaderManager::DX9VSFeatureAfterEffect oVSFeature9;
	oVSFeature9.stKey.ulShaderVer	  = 20;
	oVSFeature9.stKey.ulEffectId      = AE_TYPE_HeadLight;
	oVSFeature9.stKey.ulEffectSubType = 0;
	pVertexShader = DX9GetVertexShaderManager()->GetShader(&oVSFeature9);

	DX9VertexShaderManager::DX9VSFeatureAfterEffect oVSFeature10;
	oVSFeature10.stKey.ulShaderVer	   = 20;
	oVSFeature10.stKey.ulEffectId      = AE_TYPE_Gamma;
	oVSFeature10.stKey.ulEffectSubType = 0;
	pVertexShader = DX9GetVertexShaderManager()->GetShader(&oVSFeature10);

}

void DX9VertexShaderManager::DX9VSFeatureSpaceBump::AddSpecificFeatures(CHAR* _szFeatureDefinition)
{
	DX9_APPEND_DEFINE(1, "INPUT_COLOR0");
	DX9_APPEND_DEFINE(1, "INPUT_TEXCOORD0");
}

void DX9VertexShaderManager::DX9VSFeatureSpaceBump::PreCache()
{
	DX9VertexShaderManager::DX9VSFeatureSpaceBump oVSFeature;
	oVSFeature.stKey.ulShaderVer	= 20;
	DX9VertexShader* pVertexShader = DX9GetVertexShaderManager()->GetShader(&oVSFeature);
}


// ------------------------------------------------------------------------------------------------
// Name   : DX9VertexShaderManager::DX9VSFeatureAdvancedWater::AddSpecificFeatures
// Descr. : Add specific water render features
// ------------------------------------------------------------------------------------------------
void DX9VertexShaderManager::DX9VSFeatureAdvancedWater::AddSpecificFeatures(CHAR* _szFeatureDefinition)
{
	char szTemp[512];

	// Volume fog Id
	sprintf_s(szTemp, "ADVANCEDWATER_ID %d", stKey.ulWaterPassID);
	DX9_APPEND_DEFINE(1, szTemp);
}

void DX9VertexShaderManager::DX9VSFeatureAdvancedWater::PreCache()
{
	DX9VertexShader* pVertexShader = NULL;

	DX9VertexShaderManager::DX9VSFeatureAdvancedWater oVSFeature1;
	oVSFeature1.stKey.ulShaderVer		= 11;
	oVSFeature1.stKey.ulWaterPassID		= ADVANCEDWATER_TYPE_REFRACTIONMASK;
	oVSFeature1.stKey.ulAssemble		= 1;
	pVertexShader = DX9GetVertexShaderManager()->GetShader(&oVSFeature1);

	DX9VertexShaderManager::DX9VSFeatureAdvancedWater oVSFeature2;
	oVSFeature2.stKey.ulShaderVer		= 20;
	oVSFeature2.stKey.ulWaterPassID		= ADVANCEDWATER_TYPE_SURFACERENDER;
	oVSFeature2.stKey.ulAssemble		= 0;
	pVertexShader = DX9GetVertexShaderManager()->GetShader(&oVSFeature2);
}

const CHAR* DX9VertexShaderManager::DX9VSFeatureAdvancedWater::GetAssembleShader()
{
	if (stKey.ulWaterPassID == ADVANCEDWATER_TYPE_REFRACTIONMASK)
	{
		const CHAR *AsmVertexString =
			"vs_1_1\n"					\
			"dcl_position v0\n"			\
			"m4x4 oPos, v0, c0\n"		\
			"";
		return AsmVertexString;
	}

	return NULL;
}

//////////////////////////////////////////////////////////////////////////
const CHAR* DX9VertexShaderManager::DX9VSFeatureGPUSkin::GetAssembleShader()
{
	if (stKey.ulGpuSkinID == GPUSKINMESH_TYPE_SKINMESH2)
	{
		const CHAR *AsmVertexString = 
			"vs_1_1											\n"\
			";----------------------------------------------\n"\
			"; v0 = position								\n"\
			"; /*v1 = blend weights*/						\n"\
			"; v2 = blend weights + blend indices			\n"\
			"; v3 = normal									\n"\
			"; v4 = texture coordinates	1 and 2				\n"\
			";----------------------------------------------\n"\
										
			";----------------------------------------------\n"\
			"; r0.w = Last blend weight						\n"\
			"; r1.xy = Blend indices(indices.x, indices.y)	\n"\
			"; r1.zw = blend weights(weights.y, weights.x)	\n"\
			"; r2 = Temp position							\n"\
			"; r3 = Temp normal								\n"\
			"; r4 = Blended position in model space			\n"\
			"; r5 = Blended normal in model space			\n"\
			";----------------------------------------------\n"\

			";----------------------------------------------\n"\
			"; Constants specified by the app;				\n"\
															
			"; c46-c255 = model space matrix palette		\n"\
			"; c8	  = vertex diffuse * light.diffuse		\n"\
			"; c7	  = ambient color						\n"\
			"; c6	  = mtl.diffuse							\n"\
			"; c2-c5  = world-view-projection matrix		\n"\
			"; c9-c12 = world matrix(unused)				\n"\
			"; c13-c16= World-View matrix					\n"\
			"; c17	  =	Dir Light Ambient(unused)			\n"\
			"; c18	  =	Dir Light Diffuse(unused)			\n"\
			"; c19	  =	Dir Light Specular(w is shininess)	\n"\
			"; c1	  = light direction						\n"\
			"; c0	  = {1, 1.02f, 0, 765.01f};				\n"\
			";----------------------------------------------\n"\
														
			";----------------------------------------------\n"\
			"; oPos	  = Output position						\n"\
			"; oD0	  = Diffuse								\n"\
			"; oD1	  = Specular							\n"\
			"; oT0	  = mesh texture coordinates			\n"\
			"; oT1	  = normal.xy in camera space			\n"\
			"; oT2	  = normal in view space				\n"\
			"; oT3	  = eye direction in view space			\n"\
			"; oT4	  = light direction						\n"\
			"; oT5	  = c7 ambient color					\n"\
			"; oT6	  = c8 vertex diffuse * light.diffuse	\n"\
			"; oT7	  = Dir Light Specular(w is shininess)	\n"\
			";----------------------------------------------\n"\
														
			"dcl_position v0;								\n"\
			";dcl_blendweight v1;							\n"\
			"dcl_blendindices v2;							\n"\
			"dcl_normal v3;									\n"\
			"dcl_texcoord0 v4;								\n"\
			"												\n"\
			"// Compensate for lack of UBYTE4 on Geforce3	\n"\
			"mul r1,v2.zyxw,c0.wwyy							\n"\
			"												\n"\
			"												\n"\
			"//first compute the last blending weight		\n"\
			";dp3 r0.w,v1.xyz,c0.xzz;						\n"\
			"mov r0.w, r1.w									\n"\
			"add r0.w,-r0.w,c0.x							\n"\
			"												\n"\
			"//Set 1										\n"\
			"mov a0.x,r1.x									\n"\
			"m4x3 r4.xyz,v0,c[a0.x + 46];					\n"\
			"m3x3 r5.xyz,v3,c[a0.x + 46];					\n"\
			"												\n"\
			"//blend them									\n"\
			"mul r4.xyz,r4.xyz,r1.wwww						\n"\
			"mul r5.xyz,r5.xyz,r1.wwww						\n"\
			"												\n"\
			"//Set 2										\n"\
			"mov a0.x,r1.y									\n"\
			"m4x3 r2.xyz,v0,c[a0.x + 46];					\n"\
			"m3x3 r3.xyz,v3,c[a0.x + 46];					\n"\
			"												\n"\
			"//add them in									\n"\
			"mad r4.xyz,r2.xyz,r0.wwww,r4;					\n"\
			"mad r5.xyz,r3.xyz,r0.wwww,r5;					\n"\
			"												\n"\
			"//compute position								\n"\
			"mov r4.w, c0.x									\n"\
			"m4x4 r6, r4, c2								\n"\
			"mov oPos, r6									\n"\
		

			"// Transform normal to camera space to get tex coord1.	\n"\
			"m3x3 r3.xyz, r5.xyz, c13						\n"\
			"mov r7.xyz, r3.xyz								\n"\
			"// normalize r7 normals						\n"\
			"dp3 r7.w, r7, r7								\n"\
			"rsq r7.w, r7.w									\n"\
			"mul r7, r7, r7.w								\n"\

			"mov r3.zw, c0.zz								\n"\
			"// normalize normals							\n"\
			"dp3 r3.w, r3, r3;								\n"\
			"rsq r3.w, r3.w;								\n"\
			"mul r3, r3, r3.w;								\n"\

			"; Do the lighting calculation					\n"\
			"dp3 r1.x, r7, c1      ; normal dot light		\n"\
			";lit r1, r1									\n"\
			"mul r0, r1.x, c8		; Multiply with diffuse	\n"\
			"add r0, r0, c7			; Add in ambient		\n"\
			"mov r0.w, c6.w			; Get Mtl Alpha			\n"\
			"min r0, r0, c0.x     ; clamp if > 1			\n"\
			"mov oD0, r0									\n"\

			"; Copy texture coordinate						\n"\
			"mov oT0.xy, v4.xy								\n"\
			"// normal.xy in camera space as Tex1			\n"\
			"mov oT1.xy, r3.xy								\n"\
			"// normal in view space as Tex2				\n"\
			"mov oT2.xyz, r7.xyz							\n"\
			"// eye direction in view space as Tex3			\n"\
			"m4x4 r8, r4, c13								\n"\
			"sub oT3, c0.zzzz, r8							\n"\
			"// light dir in view space as Tex4				\n"\
			"mov oT4, c1									\n"\
			"mov oT5, c7									\n"\
			"mov oT6, c8									\n"\
			"mov oT7, c19									\n"\
			"";	

		return AsmVertexString;	
	}
	else if( stKey.ulGpuSkinID == GPUSKINMESH_TYPE_SKINMESH2_PROJECTSHADOW )
	{
		const CHAR *AsmVertexString = 
			"vs_1_1											\n"\
			";----------------------------------------------\n"\
			"; v0 = position								\n"\
			"; /*v1 = blend weights	*/						\n"\
			"; v2 = blend weights + blend indices			\n"\
			"; v3 = normal									\n"\
			"; v4 = texture coordinates	1 and 2				\n"\
			";----------------------------------------------\n"\

			";----------------------------------------------\n"\
			"; r0.w = Last blend weight						\n"\
			"; r1.xy = Blend indices(indices.x, indices.y)	\n"\
			"; r1.zw = blend weights(weights.y, weights.x)	\n"\
			"; r2 = Temp position							\n"\
			"; r4 = Blended position in world space			\n"\
			";----------------------------------------------\n"\

			";----------------------------------------------\n"\
			"; Constants specified by the app;				\n"\

			"; c46-c255 = model space matrix palette		\n"\
			"; c9-c12 = for LIGHT world-view-proj matrix	\n"\
			"; c0	  = {1, 1.02f, 0, 765.01f};				\n"\
			";----------------------------------------------\n"\

			";----------------------------------------------\n"\
			"; oPos	  = Output position						\n"\
			"; oT0	  = texture coordinates					\n"\
			"; oT1	  = Depth value							\n"\
			";----------------------------------------------\n"\

			"dcl_position v0;								\n"\
			";dcl_blendweight v1;							\n"\
			"dcl_blendindices v2;							\n"\
			"dcl_normal v3;									\n"\
			"dcl_texcoord0 v4;								\n"\
			"												\n"\
			"// Compensate for lack of UBYTE4 on Geforce3	\n"\
			"mul r1,v2.zyxw,c0.wwyy							\n"\
			"												\n"\
			"												\n"\
			"//first compute the last blending weight		\n"\
			";dp3 r0.w,v1.xyz,c0.xzz;						\n"\
			"mov r0.w, r1.w									\n"\
			"add r0.w,-r0.w,c0.x							\n"\
			"												\n"\
			"//Set 1										\n"\
			"mov a0.x,r1.x									\n"\
			"m4x3 r4.xyz,v0,c[a0.x + 46];					\n"\
			";m3x3 r5.xyz,v3,c[a0.x + 46];					\n"\
			"												\n"\
			"//blend them									\n"\
			"mul r4.xyz,r4.xyz,r1.wwww						\n"\
			";mul r5.xyz,r5.xyz,r1.wwww						\n"\
			"												\n"\
			"//Set 2										\n"\
			"mov a0.x,r1.y									\n"\
			"m4x3 r2.xyz,v0,c[a0.x + 46];					\n"\
			";m3x3 r3.xyz,v3,c[a0.x + 46];					\n"\
			"												\n"\
			"//add them in									\n"\
			"mad r4.xyz,r2.xyz,r0.wwww,r4;					\n"\
			";mad r5.xyz,r3.xyz,r0.wwww,r5;					\n"\
			"												\n"\
			"//compute position								\n"\
			"mov r4.w,c0.x									\n"\
			"// Transform position							\n"\
			"m4x4 r6, r4, c9								\n"\
			"mov oPos, r6									\n"\
/*
			"// normalize normals							\n"\
			"dp3 r5.w, r5, r5;								\n"\
			"rsq r5.w, r5.w;								\n"\
			"mul r5, r5, r5.w;								\n"\

			"; Do the lighting calculation					\n"\
			"dp3 r1.x, r5, c1      ; normal dot light		\n"\
			"lit r1, r1										\n"\
			"mul r0, r1.y, c8		; Multiply with diffuse	\n"\
			"add r0, r0, c7			; Add in ambient		\n"\
			"mov r0.w, c6.w			; Get Mtl Alpha			\n"\
			"min oD0, r0, c0.x     ; clamp if > 1			\n"\
*/
			"; Copy texture coordinate						\n"\
			"mov oT0, v4									\n"\
			"mov oT1.xyzw, r6.z								\n"\
			"";
		return AsmVertexString;	
	}
	else if( stKey.ulGpuSkinID == GPUSKINMESH_TYPE_SKINMESH2_RECEIVESHADOW )
	{
		const CHAR *AsmVertexString = 
			"vs_1_1											\n"\
			";----------------------------------------------\n"\
			"; v0 = position								\n"\
			"; /*v1 = blend weights*/						\n"\
			"; v2 = blend weights + blend indices			\n"\
			"; v3 = normal									\n"\
			"; v4 = texture coordinates	1 and 2				\n"\
			";----------------------------------------------\n"\

			";----------------------------------------------\n"\
			"; r0.w = Last blend weight						\n"\
			"; r1.xy = Blend indices(indices.x, indices.y)	\n"\
			"; r1.zw = blend weights(weights.y, weights.x)	\n"\
			"; r2 = Temp position							\n"\
			"; r4 = Blended position in world space			\n"\
			";----------------------------------------------\n"\

			";----------------------------------------------\n"\
			"; Constants specified by the app;				\n"\
			"; c5-c8   = ProjectedCloudLayer matrix			\n"\
			"; c9-c12  = WVP matrix							\n"\
			"; c13-c16 = world to light proj matrix			\n"\
			"; c17-c20 = shadow projection for sample 1		\n"\
			"; c21-c24 = shadow projection for sample 2		\n"\
			"; c25-c28 = shadow projection for sample 3		\n"\
			"; c33-c36 = shadow projection for sample 4		\n"\
			"; c32     = ( x = z bias y = 1 z = 0.0f )		\n"\
			"; c37-c40 = World-View matrix					\n"\
			"; c41     = DOF Focal Plane					\n"\
			"; c42     = {HyperfocalDistance, MaxBlurFactor, 0, 0}\n"\
			"; c46-c255 = model space matrix palette		\n"\
			"; c0	  = {1, 1.02f, 0, 765.01f};				\n"\
			";----------------------------------------------\n"\

			";----------------------------------------------\n"\
			"; oPos	  = Output position						\n"\
			"; oT4	  = texture coordinates					\n"\
			"; oT0 - oT3 = shadow texture coordinates for sample 0-3	\n"\
			"; oT5	  = Projected CloudLayer texture coord	\n"\
			"; oD1.y  = Z-bias depth						\n"\
			"; oD1.z  = correct 1 - Z depth					\n"\
			"; oD1.x  = DOF factor							\n"\

			";----------------------------------------------\n"\

			"dcl_position v0;								\n"\
			";dcl_blendweight v1;							\n"\
			"dcl_blendindices v2;							\n"\
			"dcl_normal v3;									\n"\
			"dcl_texcoord0 v4;								\n"\
			"												\n"\
			"// Compensate for lack of UBYTE4 on Geforce3	\n"\
			"mul r1,v2.zyxw,c0.wwyy							\n"\
			"												\n"\
			"												\n"\
			"//first compute the last blending weight		\n"\
			";dp3 r0.w,v1.xyz,c0.xzz;						\n"\
			"mov r0.w, r1.w									\n"\
			"add r0.w,-r0.w,c0.x							\n"\
			"												\n"\
			"//Set 1										\n"\
			"mov a0.x,r1.x									\n"\
			"m4x3 r4.xyz,v0,c[a0.x + 46];					\n"\
			"												\n"\
			"//blend them									\n"\
			"mul r4.xyz,r4.xyz,r1.wwww						\n"\
			"												\n"\
			"//Set 2										\n"\
			"mov a0.x,r1.y									\n"\
			"m4x3 r2.xyz,v0,c[a0.x + 46];					\n"\
			"												\n"\
			"//add them in									\n"\
			"mad r4.xyz,r2.xyz,r0.wwww,r4;					\n"\
			"mov r4.w,c0.x									\n"\

			"// Transform position							\n"\
			"m4x4 r2, r4, c9								\n"\
			"mov oPos, r2									\n"\
			"rcp r3.w, r2.w									\n"\
			"mul r2.z, r2.z, r3.w							\n"\
			"sub r2, c32.yyyy, r2.zzzz						\n"\
			"// Compute texture coordinates for 4 shadow samples				\n"\
			"m4x4 oT0, r4, c17								\n"\
			"m4x4 oT1, r4, c21								\n"\
			"m4x4 oT2, r4, c25								\n"\
			"m4x4 oT3, r4, c33								\n"\
			"// Compute texture coordinates for ProjectedCloudLayer Texture		\n"\
			"m4x4 oT5, r4, c5								\n"\

			"// Compute DOF Blend Factor					\n"\
			"// Compute View Space Obj position				\n"\
			"m4x4 r3, r4, c37								\n"\
			"mov r3.w, c0.x									\n"\
			"dp4 r3, r3, c41								\n"\
			"// Pixel smaller than focus Plane is clear		\n"\
			"max r3.x, r3.x, c32.z							\n"\
			"// Pixel in DOF BlurField is liner to blur		\n"\
			"mul r3.x, r3.x, c42.x							\n"\
			"mul r3.x, r3.x, r3.x							\n"\

			"// Transform Z into projected light space		\n"\
			"m4x4 r1, r4, c13								\n"\
			"mov oT4, v4									\n"\
			"// Add z bias to oD1.y							\n"\
			"add oD1.y, r1.z, c32.x							\n"\
			"// oD1.z is current Depth						\n"\
			"mov oD1.z, r2.z								\n"\
			"// oD1.x is DOF blend factor					\n"\
			"min oD1.x, r3.x, c42.y							\n"\
			"";
		return AsmVertexString;
	}
	else if( stKey.ulGpuSkinID == GPUSKINMESH_TYPE_SKINMESH2_ALPHADOFDEPTH )
	{
		const CHAR *AsmVertexString = 
			"vs_1_1											\n"\
			";----------------------------------------------\n"\
			"; v0 = position								\n"\
			"; /*v1 = blend weights*/						\n"\
			"; v2 = blend weights + blend indices			\n"\
			"; v3 = normal									\n"\
			"; v4 = vertex color							\n"\
			";----------------------------------------------\n"\

			";----------------------------------------------\n"\
			"; r0.w = Last blend weight						\n"\
			"; r1.xy = Blend indices(indices.x, indices.y)	\n"\
			"; r1.zw = blend weights(weights.y, weights.x)	\n"\
			"; r2 = Temp position							\n"\
			"; r4 = Blended position in world space			\n"\
			";----------------------------------------------\n"\

			";----------------------------------------------\n"\
			"; Constants specified by the app;				\n"\
			"; c9-c12  = WVP matrix							\n"\
			"; c32     = ( x = z bias y = 1 z = 0.0f )		\n"\
			"; c37-c40 = World-View matrix					\n"\
			"; c41     = DOF Focal Plane					\n"\
			"; c42     = {HyperfocalDistance, MaxBlurFactor, 0, 0}\n"\
			"; c46-c255 = model space matrix palette		\n"\
			"; c0	  = {1, 1.02f, 0, 765.01f};				\n"\
			";----------------------------------------------\n"\

			";----------------------------------------------\n"\
			"; oPos	  = Output position						\n"\
			"; oT5.y  = correct 1 - Z depth					\n"\
			"; oT5.z  = DOF factor							\n"\
			";----------------------------------------------\n"\

			"dcl_position v0;								\n"\
			";dcl_blendweight v1;							\n"\
			"dcl_blendindices v2;							\n"\
			"dcl_normal v3;									\n"\
			"dcl_color v4;									\n"\
			"												\n"\
			"// Compensate for lack of UBYTE4 on Geforce3	\n"\
			"mul r1,v2.zyxw,c0.wwyy							\n"\
			"												\n"\
			"												\n"\
			"//first compute the last blending weight		\n"\
			";dp3 r0.w,v1.xyz,c0.xzz;						\n"\
			"mov r0.w, r1.w									\n"\
			"add r0.w,-r0.w,c0.x							\n"\
			"												\n"\
			"//Set 1										\n"\
			"mov a0.x,r1.x									\n"\
			"m4x3 r4.xyz,v0,c[a0.x + 46];					\n"\
			"												\n"\
			"//blend them									\n"\
			"mul r4.xyz,r4.xyz,r1.wwww						\n"\
			"												\n"\
			"//Set 2										\n"\
			"mov a0.x,r1.y									\n"\
			"m4x3 r2.xyz,v0,c[a0.x + 46];					\n"\
			"												\n"\
			"//add them in									\n"\
			"mad r4.xyz,r2.xyz,r0.wwww,r4;					\n"\
			"mov r4.w,c0.x									\n"\

			"// Transform position							\n"\
			"m4x4 r2, r4, c9								\n"\
			"mov oPos, r2									\n"\
			"rcp r3.w, r2.w									\n"\
			"mul r2.z, r2.z, r3.w							\n"\
			"sub r2, c32.yyyy, r2.zzzz						\n"\

			"// Compute DOF Blend Factor					\n"\
			"// Compute View Space Obj position				\n"\
			"m4x4 r3, r4, c37								\n"\
			"mov r3.w, c0.x									\n"\
			"dp4 r3, r3, c41								\n"\
			"// Pixel smaller than focus Plane is clear		\n"\
			"max r3.x, r3.x, c32.z							\n"\
			"// Pixel in DOF BlurField is liner to blur		\n"\
			"mul r3.x, r3.x, c42.x							\n"\
			"mul r3.x, r3.x, r3.x							\n"\

			"// get alpha value of vertex color to oT4.x	\n"\
			"mov oT4.xyzw, v4.wwww							\n"\

			"mov oT5.xw, c32.zz								\n"\
			"// oT5.y is current Depth						\n"\
			"mov oT5.y, r2.z								\n"\
			"// oT5.z is DOF blend factor					\n"\
			"min oT5.z, r3.x, c42.y							\n"\

			"";
		return AsmVertexString;
	}
	return NULL;											
}

void DX9VertexShaderManager::DX9VSFeatureGPUSkin::PreCache()
{
	DX9VertexShader* pVertexShader = NULL;


	DX9VertexShaderManager::DX9VSFeatureGPUSkin oVSFeature2;
	oVSFeature2.stKey.ulShaderVer		= 11;
	oVSFeature2.stKey.ulGpuSkinID		= GPUSKINMESH_TYPE_SKINMESH2;
	oVSFeature2.stKey.ulAssemble		= 1;
	pVertexShader = DX9GetVertexShaderManager()->GetShader(&oVSFeature2);


	DX9VertexShaderManager::DX9VSFeatureGPUSkin oVSFeature3;
	oVSFeature3.stKey.ulShaderVer		= 11;
	oVSFeature3.stKey.ulGpuSkinID		= GPUSKINMESH_TYPE_SKINMESH2_PROJECTSHADOW;
	oVSFeature3.stKey.ulAssemble		= 1;
	pVertexShader = DX9GetVertexShaderManager()->GetShader(&oVSFeature3);


	DX9VertexShaderManager::DX9VSFeatureGPUSkin oVSFeature4;
	oVSFeature4.stKey.ulShaderVer		= 11;
	oVSFeature4.stKey.ulGpuSkinID		= GPUSKINMESH_TYPE_SKINMESH2_RECEIVESHADOW;
	oVSFeature4.stKey.ulAssemble		= 1;
	pVertexShader = DX9GetVertexShaderManager()->GetShader(&oVSFeature4);


	DX9VertexShaderManager::DX9VSFeatureGPUSkin oVSFeature5;
	oVSFeature5.stKey.ulShaderVer		= 11;
	oVSFeature5.stKey.ulGpuSkinID		= GPUSKINMESH_TYPE_SKINMESH2_ALPHADOFDEPTH;
	oVSFeature5.stKey.ulAssemble		= 1;
	pVertexShader = DX9GetVertexShaderManager()->GetShader(&oVSFeature5);

}

//////////////////////////////////////////////////////////////////////////
const CHAR* DX9VertexShaderManager::DX9VSFeatureShadowmap::GetAssembleShader()
{
	if( stKey.ulShadowpassID == GPUSHADOWMAP_TYPE_CASTSHADOWMAP )
	{
		const CHAR *AsmVertexString = 
			"vs_1_1											\n"\
			";----------------------------------------------\n"\
			"; v0 = position								\n"\
			";----------------------------------------------\n"\
			"; c0-c3   = transform matrix for light			\n"\

			"dcl_position v0								\n"\
			"dcl_texcoord0 v4								\n"\

			"// Transform position							\n"\
			"m4x4 r0, v0, c0								\n"\
			"mov oPos, r0									\n"\
			"mov oT0, v4									\n"\
			"// Output Z value for shadowmap				\n"\
			"mov oT1.xyzw, r0.z								\n"\
			"";	
		return AsmVertexString;	
	}
	else if( stKey.ulShadowpassID == GPUSHADOWMAP_TYPE_RECEIVESHADOW )
	{
		const CHAR *AsmVertexString = 
			"vs_1_1											\n"\
			";----------------------------------------------\n"\
			"; v0 = position								\n"\
			";----------------------------------------------\n"\
			"; c0-c3   = MVP								\n"\
			"; c4-c7   = world to light proj matrix			\n"\
			"; c8-c11  = shadow projection for sample 1		\n"\
			"; c12-c15 = shadow projection for sample 2		\n"\
			"; c16-c19 = shadow projection for sample 3		\n"\
			"; c20-c23 = shadow projection for sample 4		\n"\
			"; c30     = light dir							\n"\
			"; c31     = diffuse light						\n"\
			"; c32     = (x = z bias y = 1 z = 0.0f)		\n"\
			"; c33-c36  = ProjectedCloudLayer matrix		\n"\
			"; c37-c40 = World-View matrix					\n"\
			"; c41     = DOF Focal Plane					\n"\
			"; c42     = {HyperfocalDistance, MaxBlurFactor, 0, 0}\n"\

			"; oD1.y  = Z-bias depth						\n"\
			"; oD1.z  = correct 1 - Z depth					\n"\
			"; oD1.x  = DOF factor							\n"\

			"dcl_position v0								\n"\
			"dcl_normal v3									\n"\
			"dcl_texcoord0 v4								\n"\

			"// Transform position							\n"\
			"m4x4 r2, v0, c0								\n"\
			"mov oPos, r2									\n"\
			"rcp r3, r2.w									\n"\
			"mul r2, r2, r3									\n"\
			"sub r2, c32.yyyy, r2							\n"\
			"// Compute texture coordinates for 4 shadow samples	\n"\
			"m4x4 oT0, v0, c8								\n"\
			"m4x4 oT1, v0, c12								\n"\
			"m4x4 oT2, v0, c16								\n"\
			"m4x4 oT3, v0, c20								\n"\
			"// Compute texture coordinates for ProjectedCloudLayer Texture		\n"\
			"m4x4 oT5, v0, c33								\n"\

			"// Compute DOF Blend Factor					\n"\
			"// Compute View Space Obj position				\n"\
			"m4x4 r3, v0, c37								\n"\
			"mov r3.w, c32.y								\n"\
			"dp4 r3, r3, c41								\n"\
			"// Pixel smaller than focus Plane is clear		\n"\
			"max r3.x, r3.x, c32.z							\n"\

			"// Pixel in DOF BlurField is liner to blur		\n"\
			"mul r3.x, r3.x, c42.x							\n"\
			"mul r3.x, r3.x, r3.x							\n"\

			"// Diffuse lighting							\n"\
			"dp3 r0, v3, c30								\n"\
			"// Multiply by lighting color					\n"\
			"mul oD0, r0, c31								\n"\
			"// Transform Z into projected light space		\n"\
			"m4x4 r1, v0, c4								\n"\
			"mov oT4, v4									\n"\
			"// Add z bias to oD1.y							\n"\
			"add oD1.y, r1.z, c32.x							\n"\
			"// oD1.z is current Depth						\n"\
			"mov oD1.z, r2.z								\n"\
			"// oD1.x is DOF blend factor					\n"\
			"min oD1.x, r3.x, c42.y							\n"\
			"";	
		return AsmVertexString;
	}
	else if( stKey.ulShadowpassID == GPUSHADOWMAP_TYPE_RECEIVESHADOW_TERRAIN )
	{
		const CHAR *AsmVertexString = 
			"vs_1_1											\n"\
			";----------------------------------------------\n"\
			"; v0 = position								\n"\
			";----------------------------------------------\n"\
			"; c0-c3   = MVP								\n"\
			"; c4-c7   = world to light proj matrix			\n"\
			"; c8-c11  = shadow projection for sample 1		\n"\
			"; c12-c15 = shadow projection for sample 2		\n"\
			"; c16-c19 = shadow projection for sample 3		\n"\
			"; c20-c23 = shadow projection for sample 4		\n"\
			"; c30     = light dir							\n"\
			"; c31     = diffuse light						\n"\
			"; c32     = (x = z bias y = 1 z = 0.0f)		\n"\
			"; c33-c36  = ProjectedCloudLayer matrix		\n"\
			"; c37-c40 = World-View matrix					\n"\
			"; c41     = DOF Focal Plane					\n"\
			"; c42     = {HyperfocalDistance, MaxBlurFactor, 0, 0}\n"\

			"; oD1.x  = Z-bias depth						\n"\
			"; oD1.y  = correct 1 - Z depth					\n"\
			"; oD1.z  = DOF factor							\n"\

			"dcl_position v0								\n"\
			"dcl_normal v3									\n"\
			"dcl_color v4									\n"\

			"// Transform position							\n"\
			"m4x4 r2, v0, c0								\n"\
			"mov oPos, r2									\n"\
			"rcp r3, r2.w									\n"\
			"mul r2, r2, r3									\n"\
			"sub r2, c32.yyyy, r2							\n"\
			"// Compute texture coordinates for 4 shadow samples	\n"\
			"m4x4 oT0, v0, c8								\n"\
			"m4x4 oT1, v0, c12								\n"\
			"m4x4 oT2, v0, c16								\n"\
			"m4x4 oT3, v0, c20								\n"\
			"// Compute texture coordinates for ProjectedCloudLayer Texture		\n"\
			"m4x4 oT5, v0, c33								\n"\

			"// Compute DOF Blend Factor					\n"\
			"// Compute View Space Obj position				\n"\
			"m4x4 r3, v0, c37								\n"\
			"mov r3.w, c32.y								\n"\
			"dp4 r3, r3, c41								\n"\
			"// Pixel smaller than focus Plane is clear		\n"\
			"max r3.x, r3.x, c32.z							\n"\
			"// Pixel in DOF BlurField is liner to blur		\n"\
			"mul r3.x, r3.x, c42.x							\n"\
			"mul r3.x, r3.x, r3.x							\n"\

			"// Diffuse lighting							\n"\
			"dp3 r0, v3, c30								\n"\
			"// Multiply by lighting color					\n"\
			"mul oD0, r0, c31								\n"\
			"// Transform Z into projected light space		\n"\
			"m4x4 r1, v0, c4								\n"\
			";mov oT4, v4									\n"\
			"// Add z bias to oD1.x							\n"\
			"add oD1.x, r1.z, c32.x							\n"\
			"// oD1.y is current Depth						\n"\
			"mov oD1.y, r2.z								\n"\
			"// oD1.z is DOF blend factor					\n"\
			"min oD1.z, r3.x, c42.y							\n"\
			"";	
		return AsmVertexString;
	}
	else if( stKey.ulShadowpassID == GPUSHADOWMAP_TYPE_STUDIOTERRAIN_RENDER )
	{
		const CHAR *AsmVertexString = 
			"vs_1_1											\n"\
			";----------------------------------------------\n"\
			"; v0 = position								\n"\
			";----------------------------------------------\n"\
			"; c0-c3   = MVP								\n"\
			"; c30     = light dir							\n"\
			"; c31     = diffuse light						\n"\

			"dcl_position v0								\n"\
			"dcl_normal v3									\n"\
			"dcl_texcoord0 v4								\n"\

			"// Transform position							\n"\
			"m4x4 r1, v0, c0								\n"\
			"mov oPos, r1									\n"\

			"// Diffuse lighting							\n"\
			"dp3 r0, v3, c30								\n"\
			"// Multiply by lighting color					\n"\
			"mul oD0, r0, c31								\n"\
			"mov oT0, v4									\n"\
			"mov oT4, r1									\n"\
			"";
		return AsmVertexString;
	}
	else if( stKey.ulShadowpassID == GPUSHADOWMAP_TYPE_OBJWITHSHADOW_RENDER )
	{
		const CHAR *AsmVertexString = 
			"vs_1_1											\n"\
			";----------------------------------------------\n"\
			"; v0 = position								\n"\
			"; v2 = vertex color							\n"\
			"; v3 = texcoord0								\n"\
			"; v4 = texcoord1								\n"\
			";----------------------------------------------\n"\
			"; c0-c3   = MVP								\n"\

			"dcl_position v0								\n"\
			"dcl_color v2									\n"\
			"dcl_texcoord0 v3								\n"\
			"dcl_texcoord1 v4								\n"\

			"// Transform position							\n"\
			"m4x4 r1, v0, c0								\n"\
			"mov oPos, r1									\n"\
			"// Vertex color								\n"\
			"mov oD0, v2									\n"\

			"mov oT0, v3									\n"\
			"mov oT1, v4									\n"\
			"mov oT2, r1									\n"\


			"";
		return AsmVertexString;
	}
	else if( stKey.ulShadowpassID == GPUSHADOWMAP_TYPE_WORLDTERRAIN_RENDER )
	{
		const CHAR *AsmVertexString = 
			"vs_1_1											\n"\
			";----------------------------------------------\n"\
			"; v0 = position								\n"\
			"; v1 = vertex color							\n"\
			";----------------------------------------------\n"\
			"; c0-c3   = MVP								\n"\


			"dcl_position v0								\n"\
			"dcl_color v1									\n"\

			
			"def c4, 1.0, 1.0, 1.0, 1.0						\n"\
			"// Transform position							\n"\
			"m4x4 r1, v0, c0								\n"\
			"mov oPos, r1									\n"\

			"mov oD0, c4									\n"\
			"mov oT4, r1									\n"\
			"";
		return AsmVertexString;
	}
	else if( stKey.ulShadowpassID == GPUSHADOWMAP_TYPE_ALPHADOFDEPTH )
	{
		const CHAR *AsmVertexString = 
			"vs_1_1											\n"\
			";----------------------------------------------\n"\
			"; v0 = position								\n"\
			";----------------------------------------------\n"\
			"; c0-c3   = MVP								\n"\
			"; c32     = (x = z bias y = 1 z = 0.0f)		\n"\
			"; c37-c40 = World-View matrix					\n"\
			"; c41     = DOF Focal Plane					\n"\
			"; c42     = {HyperfocalDistance, MaxBlurFactor, 0, 0}\n"\

			"dcl_position v0								\n"\
			"dcl_texcoord0 v1								\n"\
			"dcl_color v4									\n"\

			"// Transform position							\n"\
			"m4x4 r2, v0, c0								\n"\
			"mov oPos, r2									\n"\
			"rcp r3, r2.w									\n"\
			"mul r2, r2, r3									\n"\
			"sub r2, c32.yyyy, r2							\n"\

			"// Compute DOF Blend Factor					\n"\
			"// Compute View Space Obj position				\n"\
			"m4x4 r3, v0, c37								\n"\
			"mov r3.w, c32.y								\n"\
			"dp4 r3, r3, c41								\n"\

			"// Pixel smaller than focus Plane is clear		\n"\
			"max r3.x, r3.x, c32.z							\n"\

			"// Pixel in DOF BlurField is liner to blur		\n"\
			"mul r3.x, r3.x, c42.x							\n"\
			"mul r3.x, r3.x, r3.x							\n"\

			"mov oT0, v1									\n"\

			"// get alpha value of vertex color to oT4.x	\n"\
			"mov oT4.xyzw, v4.wwww							\n"\

			"mov oT5.xw, c32.zz								\n"\
			"// oT5.y is current Depth						\n"\
			"mov oT5.y, r2.z								\n"\
			"// oT5.z is DOF blend factor					\n"\
			"min oT5.z, r3.x, c42.y							\n"\

			"";

		return AsmVertexString;
	}
	return NULL;
}

void DX9VertexShaderManager::DX9VSFeatureShadowmap::PreCache()
{
	DX9VertexShader* pVertexShader = NULL;

	DX9VertexShaderManager::DX9VSFeatureShadowmap oVSFeature1;
	oVSFeature1.stKey.ulShaderVer			= 11;
	oVSFeature1.stKey.ulShadowpassID		= GPUSHADOWMAP_TYPE_CASTSHADOWMAP;
	oVSFeature1.stKey.ulAssemble			= 1;
	pVertexShader = DX9GetVertexShaderManager()->GetShader(&oVSFeature1);

	DX9VertexShaderManager::DX9VSFeatureShadowmap oVSFeature2;
	oVSFeature2.stKey.ulShaderVer			= 11;
	oVSFeature2.stKey.ulShadowpassID		= GPUSHADOWMAP_TYPE_RECEIVESHADOW;
	oVSFeature2.stKey.ulAssemble			= 1;
	pVertexShader = DX9GetVertexShaderManager()->GetShader(&oVSFeature2);

	DX9VertexShaderManager::DX9VSFeatureShadowmap oVSFeature3;
	oVSFeature3.stKey.ulShaderVer			= 11;
	oVSFeature3.stKey.ulShadowpassID		= GPUSHADOWMAP_TYPE_STUDIOTERRAIN_RENDER;
	oVSFeature3.stKey.ulAssemble			= 1;
	pVertexShader = DX9GetVertexShaderManager()->GetShader(&oVSFeature3);

	DX9VertexShaderManager::DX9VSFeatureShadowmap oVSFeature4;
	oVSFeature4.stKey.ulShaderVer			= 11;
	oVSFeature4.stKey.ulShadowpassID		= GPUSHADOWMAP_TYPE_WORLDTERRAIN_RENDER;
	oVSFeature4.stKey.ulAssemble			= 1;
	pVertexShader = DX9GetVertexShaderManager()->GetShader(&oVSFeature4);

	DX9VertexShaderManager::DX9VSFeatureShadowmap oVSFeature5;
	oVSFeature5.stKey.ulShaderVer			= 11;
	oVSFeature5.stKey.ulShadowpassID		= GPUSHADOWMAP_TYPE_RECEIVESHADOW_TERRAIN;
	oVSFeature5.stKey.ulAssemble			= 1;
	pVertexShader = DX9GetVertexShaderManager()->GetShader(&oVSFeature5);

	DX9VertexShaderManager::DX9VSFeatureShadowmap oVSFeature7;
	oVSFeature7.stKey.ulShaderVer			= 11;
	oVSFeature7.stKey.ulShadowpassID		= GPUSHADOWMAP_TYPE_ALPHADOFDEPTH;
	oVSFeature7.stKey.ulAssemble			= 1;
	pVertexShader = DX9GetVertexShaderManager()->GetShader(&oVSFeature7);

	DX9VertexShaderManager::DX9VSFeatureShadowmap oVSFeature8;
	oVSFeature8.stKey.ulShaderVer			= 11;
	oVSFeature8.stKey.ulShadowpassID		= GPUSHADOWMAP_TYPE_OBJWITHSHADOW_RENDER;
	oVSFeature8.stKey.ulAssemble			= 1;
	pVertexShader = DX9GetVertexShaderManager()->GetShader(&oVSFeature8);
}

void DX9VertexShaderManager::DX9VSFeatureSoftParticle::PreCache()
{
	DX9VertexShader* pVertexShader = NULL;

	DX9VertexShaderManager::DX9VSFeatureSoftParticle oVSFeature;
	oVSFeature.stKey.ulShaderVer		= 20;
	pVertexShader = DX9GetVertexShaderManager()->GetShader(&oVSFeature);
}

void DX9VertexShaderManager::DX9VSFeatureSoftParticle::AddSpecificFeatures(CHAR* _szFeatureDefinition)
{
	DX9_APPEND_DEFINE(1, "INPUT_COLOR0");
	DX9_APPEND_DEFINE(1, "INPUT_TEXCOORD0");
}

void DX9VertexShaderManager::DX9VSFeatureDynamicWeather::AddSpecificFeatures(CHAR* _szFeatureDefinition)
{
	DX9_APPEND_DEFINE(1, "INPUT_TEXCOORD0");
}
void DX9VertexShaderManager::DX9VSFeatureDynamicWeather::PreCache()
{
	DX9VertexShader* pVertexShader = NULL;

	DX9VertexShaderManager::DX9VSFeatureDynamicWeather oVSFeature;
	oVSFeature.stKey.ulShaderVer = 20;
	pVertexShader = DX9GetVertexShaderManager()->GetShader(&oVSFeature);
}